//
// Copyright (c) 2024 BPer
//
#ifndef SRC_BPERICE_BPERTURNCONNECTION_H_
#define SRC_BPERICE_BPERTURNCONNECTION_H_

#include <bperice/BPerRtcStun.h>
#include <bperice/BPerRtcSocket.h>

#include <bperutil/BPerType.h>
#include <bperutil/BPerAvcType.h>
#include <bperutil/sys/BPerVector.h>

#define   BPer_Turn_Error_BadRequest       400
#define   BPer_Turn_Error_Unauthoorized    401
#define   BPer_Turn_Error_UnknowAttribute  420
#define   BPer_Turn_Error_Nonce            438
#define   BPer_Turn_Transport_Udp          0x11
#define   BPer_Turn_Transport_Tcp          0x06
#define   BPer_Turn_ChannelNumBase         0x4000
#define   BPer_Turn_Default_Lifetime       600
#define   BPer_Turn_Permission_Lifetime    300

typedef enum {
	BPerTurnNew,
	BPerTurnCredential,
	BPerTurnAllocate,
	BPerTurnPermission,
	BPerTurnBindChannel,
	BPerTurnReady,
	BPerTurnClose
} BPerTurnState;

typedef enum{
	BPerTurnNoneError,
	BPerTurnAllocateError,
	BPerTurnPermissionError,
	BPerTurnBindChannelError,
	BPerTurnRefreshError,
	BPerTurnKwnownError
}BPerTurnErrorCode;


typedef struct{
	uint16_t errorCode;
	uint16_t mappedPort;
	uint32_t mappedAddress;
	int32_t lifetime;
	uint32_t nonceLen;
	uint8_t nonce[128];

}BPerTurnResponseData;

typedef void (*bPer_turn_receive)(void *psession, char *data, int32_t size);

typedef struct {
    uint16_t channelNumber;
    uint16_t lifetime;
    BPerBool isSending;
	int32_t uid;
	uint32_t lifetimeOuttime;
	BPerTurnState state;
    void* receiveUser;
    bPer_turn_receive receive;
	BPerIpAddress address;
	BPerIpAddress xorAddress;
} BPerTurnPeer;

bPer_vector_declare2(BPerTurnPeer)

typedef struct{
	uint16_t channelNum;
	uint16_t relayPort;
	uint16_t nonceLen;
	uint16_t permissionCount;
	uint32_t relayIp;
	int32_t isStart;
	int32_t isLoop;
	int32_t waitTime;
	int32_t lifetime;
	uint32_t allocateOuttime;

	BPerTurnState state;
	BPerTurnErrorCode errorCode;
	bPer_thread_t threadId;
	bPer_thread_mutex_t turnLock;
	BPerBool hasRelayAddress;
	BPerTurnResponseData response;

	BPerIceServer* server;
	BPerRtcSocket* sock;

	char* icePwd;
	BPerBuffer* stream;

	char realm[129];
	uint8_t nonce[128];
	BPerStunLib stun;
	BPerTurnPeerVector2 peers;

}BPerTurnSession;

typedef struct{
	BPerTurnSession session;
	BPerBool (*isReady)(BPerTurnSession* session);
	BPerBool (*isAllocated)(BPerTurnSession* session);
	int32_t (*sendData)(BPerTurnSession *psession, int32_t uid,char *data, int32_t nb);
	int32_t (*addPeer)(BPerTurnSession *session,int32_t uid,void* rtcSession,bPer_turn_receive receive,char* remoteIp,uint16_t remotePort);
	int32_t (*removePeer)(BPerTurnSession *session,int32_t uid);
	int32_t (*start)(BPerTurnSession* session);
	void (*stop)(BPerTurnSession* session);
}BPerTurnConnection;

void bPer_create_turnConnection(BPerTurnConnection* conn,BPerIceServer* server,BPerRtcSocket* sock,int32_t localport);
void bPer_destroy_turnConnection(BPerTurnConnection* conn);
#endif /* SRC_BPERICE_BPERTURNCONNECTION_H_ */
